#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "epolleventhandlerimpl.h"
#include "buffersocket.h"

int EpollEventHandlerImpl ::  OnAccept( epoll_event * ptEvent )
{
	int ret = -1;
	struct sockaddr cliaddr;
	memset( &cliaddr, 0, sizeof(cliaddr) );
	socklen_t addrlen = sizeof(sockaddr);

	int connfd = accept( m_ptEpollEventMng->GetListenFd(), &cliaddr, &addrlen );
	
	if ( connfd > 0 )
	{
		SetNonBlock(connfd);
		BufferSocket * ptConn = new BufferSocket( connfd );
		ret = m_ptEpollEventMng->AddEvent( connfd, EPOLLIN, ptConn );
		if ( 0 != ret )
		{
			printf("accept, but add event error errno %d errmsg %s\n",errno, strerror(errno) );
			close(connfd);
		}
	}
	else
	{
		printf("accept fail errmsg %s \n",strerror(errno));
	}
	return ret;
}

int EpollEventHandlerImpl :: OnRead( epoll_event * ptEvent )
{
	int ret = 0, n = -1;
	BufferSocket * ptBufSocket = NULL;
	
	if ( NULL != ptEvent->data.ptr )
	{
		ptBufSocket = (BufferSocket *) ptEvent->data.ptr;
		ptBufSocket->ClearReadBuffer();

		n = ptBufSocket->ReadToBufferEx();

		if ( n == 0 )//fin
		{
			DelEvent( ptEvent, EPOLLIN );
		}
		else//n<0
		{
			if ( errno == EAGAIN )
			{
				m_ptProcessor->Process( ptBufSocket->GetReadBuffer() , ptBufSocket->GetWriteBuffer() );
				
				ret = m_ptEpollEventMng->Mod2W( ptBufSocket->GetFd() , ptBufSocket );
				
				if ( ret != 0 )
				{
					printf("Mod2w ret %d errno %d errmsg %s\n",ret,errno,strerror(errno));
					DelEvent( ptEvent, EPOLLIN );
				}
			}
			else
			{
				printf("errno %d errmsg %s\n",errno,strerror(errno));
				DelEvent( ptEvent, EPOLLIN );
			}
		}
		
	}
	return ret;
}

int EpollEventHandlerImpl :: OnWrite( epoll_event * ptEvent )
{
	int ret = -1;
	BufferSocket * ptBufSocket = (BufferSocket *) (ptEvent->data.ptr);
	if ( NULL != ptBufSocket )
	{
		ret = ptBufSocket->WriteFromBufferEx();

		if ( 0 == ret )
		{
			DelEvent( ptEvent, EPOLLOUT );
			/*
			ret = m_ptEpollEventMng->Mod2R( ptBufSocket->GetFd(), ptBufSocket );
			if ( 0 != ret )
			{
				printf("mod2r errno %d errmsg %s\n", errno, strerror(errno) );
				DelEvent( ptEvent, EPOLLOUT );
			}
			*/
		}
		else 
		{
			assert( ret < 0 );
			if ( errno == EAGAIN )
			{
				printf("write and errno == EAGAIN\n");
			}
			else
			{
				printf("write errno %d errmsg %s\n", errno, strerror(errno) );
				DelEvent( ptEvent, EPOLLOUT );
			}
		}
	}
	return ret;
}

void EpollEventHandlerImpl :: DelEvent( epoll_event * ptEvent, int event_mode )
{
	if ( NULL != ptEvent )
	{
//		printf("DEL\n");
		BufferSocket * ptBufSocket = (BufferSocket *) (ptEvent->data.ptr);
		m_ptEpollEventMng->DelEvent( ptBufSocket->GetFd() , event_mode, ptBufSocket );
		ptEvent->data.ptr = NULL;
		delete ptBufSocket;
	}
}
